#include <fstream>
#include <glog/logging.h>
#include <sys/stat.h>

#include "ji_utils.h"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include "sample_detector.h"

using namespace ev;

SampleDetector::SampleDetector() {}

bool SampleDetector::Init(ModelConfig *config)
{
    m_model_config = config;
    return true;
}

bool SampleDetector::UnInit() { return true; }

SampleDetector::~SampleDetector() { UnInit(); }

bool SampleDetector::ProcessImage(const cv::Mat &img, std::vector<ev::vision::BoxInfo> &det_results)
{
    det_results.clear();
    cv::Mat cv_in_mat1;
    // 前处理
    m_preprocessor.Run(const_cast<cv::Mat &>(img), cv_in_mat1, 640);

    // 准备输入数据
    EVModelData in;
    EVModelData out;
    EVMatData in_mat;

    in.desc = NULL;
    in.mat = &in_mat;

    in.mat_num = 1; // 输入图像数量,也可以是多张;如果是多张,则in.mat为数组指针

    in_mat.data = cv_in_mat1.data;
    in_mat.data_size = cv_in_mat1.cols * cv_in_mat1.rows * 3 * 4;
    in_mat.width = cv_in_mat1.cols;
    in_mat.height = cv_in_mat1.rows;
    in_mat.aligned_width = cv_in_mat1.cols;
    in_mat.aligned_height = cv_in_mat1.rows;
    in_mat.channel = 3;
    in_mat.loc = EV_DATA_HOST;
    in_mat.type = EV_UINT8;

    // 执行推理
    static std::mutex m_mutex; // 定义局部变量锁，被该类的所有对象共享，表示多对象时只能有一个对象在推理
    std::lock_guard<std::mutex> lock_guard(m_mutex); // 用于多线程时,线程安全
    EVDeploy::GetModel().RunInfer(m_model_config->uuid, &in, &out);
    SDKLOG(INFO) << "RunInfer done";
    // 输出的数量由out.mat_num指示,输出的数据封装在out.mat中,如果是多个输出,则out.mat为指向多个输出的指针,
    // 每一个输出的维度信息由out.mat[i]->dims指示
    // 每一个输出的名称信息由out.mat[i]->desc指示
    for (int j = 0; j < out.mat_num; ++j)
    {
        SDKLOG(INFO) << "output name: " << out.mat[j].desc;
        for (int k = 0; k < out.mat[j].dims.size(); ++k)
        {
            SDKLOG(INFO) << "dims " << k << ":" << out.mat[j].dims[k];
        }
    }

    // 后处理
    float scale = m_preprocessor.GetScale();
    m_postprocessor.Run(out.mat, det_results, scale, m_model_config->thresh, img.cols, img.rows,
                        m_model_config->nms_thresh, m_model_config->class_aware);

    // 注意释放out.mat,否则会有内存泄露!!!!
    if (out.mat)
    {
        delete[] out.mat;
    }

    return true;
}
